package ua.com.stormlabs.tiny.licenseserver.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import ua.com.stormlabs.tiny.licenseserver.beans.License;
import ua.com.stormlabs.tiny.licenseserver.storage.*;
import ua.com.stormlabs.tiny.licenseserver.storage.entities.LicenseEntity;
import ua.com.stormlabs.tiny.licenseserver.utils.ArgumentGuard;

import java.util.LinkedList;
import java.util.List;

/**
 * @author Maxim Bondarenko
 * @version 1.0 12/18/11
 */

@Service
public class LicensesServiceImpl implements LicensesService {

    private static final Logger log = LoggerFactory.getLogger(LicensesServiceImpl.class);

    @Autowired
    LicensesRepository licensesRepository;

    @Override
    public RequestResult<License> listLicenses(int pageNumber, int pageSize) {
        Pageable pageable = new PageRequest(pageNumber, pageSize);
        Page<LicenseEntity> licenseEntities = licensesRepository.findAll(pageable);

        List<License> licenses = new LinkedList<>();

        for (LicenseEntity licenseEntity : licenseEntities) {
            licenses.add(BeanConverter.convert(licenseEntity));
        }

        long licensesCount = licensesRepository.count();

        return new RequestResult<>(licenses, licensesCount);
    }

    @Override
    public License createLicense(String licenseName) throws DuplicateLicenseException {
        ArgumentGuard.checkNotNull(licenseName, "licenseName");
        ArgumentGuard.checkNotBlank(licenseName, "licenseName");

        if (licensesRepository.findByLicenseName(licenseName) != null) {
            String msg = "License with name: " + licenseName + " already exists";
            log.error(msg);
            throw new DuplicateLicenseException(msg);
        }

        LicenseEntity licenseEntity = new LicenseEntity();
        licenseEntity.setLicenseName(licenseName);

        licenseEntity = licensesRepository.saveAndFlush(licenseEntity);

        return BeanConverter.convert(licenseEntity);
    }

    @Override
    public License getLicenseById(int id) throws LicenseNotFoundException {
        ArgumentGuard.checkNotNegativeInteger(id, "id");

        LicenseEntity licenseEntity = licensesRepository.findOne(id);

        if (licenseEntity == null) {
            String msg = "License with id [" + id + "] doesn't exist";
            log.error(msg);
            throw new LicenseNotFoundException(msg);
        }

        return BeanConverter.convert(licenseEntity);
    }

    @Override
    public License getLicenseByName(String licenseName) throws LicenseNotFoundException {
        ArgumentGuard.checkNotNull(licenseName, "licenseName");
        ArgumentGuard.checkNotBlank(licenseName, "licenseName");

        LicenseEntity licenseEntity = licensesRepository.findByLicenseName(licenseName);

        if (licenseEntity == null) {
            String msg = "License with name [" + licenseName + "] doesn't exist";
            log.error(msg);
            throw new LicenseNotFoundException(msg);
        }

        return BeanConverter.convert(licenseEntity);
    }

    @Override
    public void deleteLicenseById(int id) throws LicenseNotFoundException {
        ArgumentGuard.checkNotNegativeInteger(id, "id");

        LicenseEntity licenseEntity = licensesRepository.findOne(id);

        if (licenseEntity == null) {
            String msg = "License with id [" + id + "] doesn't exist";
            log.error(msg);
            throw new LicenseNotFoundException(msg);
        }

        licensesRepository.delete(id);
    }

    @Override
    public List<License> listAllLicenses() {
        List<LicenseEntity> licenseEntities = licensesRepository.findAll();

        List<License> licenses = new LinkedList<>();

        for (LicenseEntity licenseEntity : licenseEntities) {
            licenses.add(BeanConverter.convert(licenseEntity));
        }

        return licenses;
    }

}
